#include "TerrainUpdaterBedWars.h"

#include "GameSingleton.h"
#include "ServerConfigure.h"
#include "Subsystems/SubsystemTerrain.h"
#include "Subsystems/SubsystemWeather.h"
#include "Subsystems/SubsystemPlayers.h"
#include "Subsystems/SubsystemTimeOfDay.h"
#include "Subsystems/BlockBehaviors/SubsystemBlockBehaviors.h"

#include "Player/PlayerData.h"
#include "Components/ComponentPlayer.h"
#include "Components/ComponentCreature.h"
#include "Components/ComponentBody.h"
#include "Log.h"
#include "GameSingleton.h"
#include "GameThreadPool.hpp"


namespace BedWars
{
    void TerrainUpdaterBedWars::update(float dt)
    {

        // 检测并加载玩家周边的区块
        if (playersRoundCheckFinish == true)
        {
            playersRoundCheckFinish = false;
            GameSingleton::gameNoWaitThreadPool->push_task([this]
            {
                playersRoundCheck();
            });
        }


        if(m_lastSkylightValue != m_subsystemWeather->skylightValue)
        {
            m_lastSkylightValue = m_subsystemWeather->skylightValue;
            m_isResetSkylightValue = true;
        }

        std::vector<TerrainChunk*> chunkVec;
        m_subsystemTerrain->getAllTerrainChunk(chunkVec);

        auto *blockBehaviorsByContents = m_subsystemBlockBehaviors->getBlockBehaviorsByContents();

        for(auto it = chunkVec.begin(); it != chunkVec.end(); ++it)
        {
            TerrainChunk *terrainChunk = *it;

            // 跳过16个文件区块的回收处理，超过的会回收，防止外挂跑图
            Point2 regionPoint(terrainChunk->coords.posX >> 4, terrainChunk->coords.posY >> 4);
            if(regionPoint.posX >= -1 && regionPoint.posX <= 2 && regionPoint.posY >= -1 && regionPoint.posY <= 2)
            {
                continue;
            }

            // 这里不需要判断remove,因为再此update调用之前，已经将需要remove的区块都回收掉了
            if(terrainChunk->recycleTime >= GameSingleton::serverConfigure->terrainChunkRecycleTime)
            {
                for(int32_t num = 0; num < 1024; ++num)
                {
                    for(auto &behavior : blockBehaviorsByContents[num])
                    {
                        behavior->onChunkDiscarding(terrainChunk);
                    }
                }

                terrainChunk->isRemove = true;
                continue;
            }
            terrainChunk->recycleTime += dt;
        }


        if(m_subsystemTimeOfDay->periodicGameTimeEvent(3.5, 0.0))
        {
            bool isResetSkylightValue = m_isResetSkylightValue;
            m_isResetSkylightValue = false;

            for(auto it = chunkVec.begin(); it != chunkVec.end(); ++it)
            {
                TerrainChunk *terrainChunk = *it;
                if(terrainChunk->State >= TerrainChunkState::InvalidLight)
                {
                    if(isResetSkylightValue == true)
                    {
                        terrainChunk->State = TerrainChunkState::InvalidLight;
                    }
                    if (terrainChunk->State < TerrainChunkState::Valid)
                    {
                        m_waitUpdateSingleStepCoordSet.insert(terrainChunk->coords);
                        // updateChunkSingleStep(terrainChunk, m_subsystemWeather->skylightValue);
                    }
                }
            }
        }

        // 光照加载用的是单线程加载，所以一次性不能加载过多，不然会卡到tick
        if (m_waitUpdateSingleStepCoordSet.size() > 0)
        {
            Point2 coords = *(m_waitUpdateSingleStepCoordSet.begin());
            m_waitUpdateSingleStepCoordSet.erase(m_waitUpdateSingleStepCoordSet.begin());
            TerrainChunk *chunk = m_subsystemTerrain->getTerrainChunk(coords.posX, coords.posY);
            if (chunk != nullptr)
            {
                while(chunk->State < TerrainChunkState::Valid)
                {
                    updateChunkSingleStep(chunk, m_subsystemWeather->skylightValue);
                }
            }
        }
    }



}